using Baula.Testing.Common;
using Baula.TextGen.ActiveTemplating.Tokenizer.TokenParsers;
using Baula.TextGen.ActiveTemplating.Tokenizer.Tokens;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Baula.TextGen.ActiveTemplating.Tests.Tokenizer.TokenParsers
{
    [TestClass]
    public class InlineExpressionParserTests : TokenParserTestsBase
    {
        [TestMethod]
        public void CanAppend_WithTokenPrefixOnOpenToken_ReturnsTrue()
        {
            SetInitialContent("");
            var actual = _parser.CanAppend(InlineExpressionParser.TokenPrefix);
            Assert.IsTrue(actual);
        }

        [TestMethod]
        public void Append_OnClosedToken_ThrowsException()
        {
            SetContentAndClose("some content");
            ExceptionAssert.Expect<CannotAppendToClosedTokenException>(() => _parser.Append('x'));
        }

        [TestMethod]
        public void CreateToken_AfterSingleQuote_ThrowsException()
        {
            SetInitialContent("\"");
            _parser.Append(InlineExpressionParser.TokenSuffix);  // inside string does not end token

            var exception = ExceptionAssert.Expect(() => _parser.CreateToken());
            
            Assert.IsInstanceOfType(exception, typeof (MissingEndOfStringExpressionException));
        }

        [TestMethod]
        public void CreateToken_AfterClosedSimpleString_DoesNotThrowException()
        {
            SetInitialContent("\"x\"");
            _parser.Append(InlineExpressionParser.TokenSuffix);  // End token

            _parser.CreateToken();

            // Assert.Pass()
        }

        [TestMethod]
        public void CreateToken_AfterClosedStringContainingEscapedQuotes_DoesNotThrowException()
        {
            SetInitialContent("\"x\"\"y\"");
            _parser.Append(InlineExpressionParser.TokenSuffix);  // End token

            _parser.CreateToken();

            // Assert.Pass()
        }

        [TestMethod]
        public void CreateToken_OnUnclosedToken_ThrowsException()
        {
            SetInitialContent("some content");

            ExceptionAssert.Expect<MissingEndOfInlineExpressionException>(() => _parser.CreateToken());
        }

        [TestMethod]
        public void CreateToken_OnClosedToken_DoesNotThrowException()
        {
            SetContentAndClose("some content");

            _parser.CreateToken();

            // Assert.Pass()
        }

        [TestMethod]
        public void CreateToken_OnClosedToken_ReturnsTheCorrectExpression()
        {
            SetContentAndClose("Some content");

            var token = (InlineExpressionToken)_parser.CreateToken();

            Assert.AreEqual("Some content", token.Expression);
        }

        protected override ITokenParser CreateParser()
        {
            return new InlineExpressionParser();
        }

        protected override void CloseToken(ITokenParser parser)
        {
            parser.Append(InlineExpressionParser.TokenSuffix);
        }
    }
}